package cz.uhk.max.matrix.impl;

import java.util.ArrayList;
import java.util.List;

import cz.uhk.max.matrix.Col;
import cz.uhk.max.matrix.Matrix;
import cz.uhk.max.matrix.Row;


public class MatrixDao {
	public static Col max(Col ai, Col ay) {
		if (ai.getValue() >= ay.getValue()) {
			return ai;
		} else {
			return ay;
		}
	}
	
	public static Col min(Col ai, Col ay){
		if (ai.getValue() <= ay.getValue()) {
			return ai;
		} else {
			return ay;
		}
	}
	
	public static Matrix findXCandidate(Matrix A) {
		//nalezena matice obsahuje kandidaty na matici X
		//poloha v kter� je nalezen� hodnota v matici xCandidate 
		//odpov�d� indexu sloupce v p�vodn� matici A
		Matrix m = new Matrix(A);
		//matice xCandidate m� jeden sloupec  a tolik ��dk�, koli m� matice A sloupc�
//		System.out.println("po�et slouc� v matici A:" + m.getColsCount());
		Matrix xCandidate = new Matrix(m.getColsCount(),1);
		Col max = new Col();
		for (int i = 0; i < m.getRowsCount(); i++) {
			//pro ka�d� ��dek ze vstupn� matice se nalezne maxim�ln� hodnota
			//ulo�� se na takovou pozici v matici x, kter� sv�m indexem odpov�d� p�vodn�mu um�st�n� v matici A
			max = maximum(m.getRows().get(i).getCols());
//			System.out.println("nalezene indexy v matici A: i-" + i + ", j-" + max.getJ());
//			System.out.println("nalezena hodnota je:" + max.getValue());
			xCandidate.setCol(max.getJ(), 0, max.getValue());
		}
		return xCandidate;
	}
	
	public static Matrix findX(Matrix xa, Matrix xb) {
		Matrix a = new Matrix(xa);
		Matrix b = new Matrix(xb);
		//matice x ma tolik radku, kolik matice A sloupcu
		Matrix x = new Matrix(a.getRowsCount(),1);
		for (int i = 0; i < a.getRowsCount(); i++) {
			//porovn�n� maxim nalezen�ch v matici A a B
			//men�� hodnota je v�herce
			if (a.getCol(i, 0).getValue() < b.getCol(i, 0).getValue()) {
				x.setCol(i, 0, a.getCol(i, 0).getValue());
			}else
			{
				x.setCol(i, 0, b.getCol(i, 0).getValue());
			}
		}
		return x;
	}
	
	public static Col maximum (List<Col> cols) {
		//pro nalezen� maxima ze seznamu sloupc�
		//metoda vrac� sloupec Col s maxim�ln� hodnotou
		List<Col> minsList = new ArrayList<Col>(cols);
		Col pom;
		  for (int i = 0; i < (minsList.size()-1); i++) {
		      if (minsList.get(i+1).getValue() < minsList.get(i).getValue()) {
		        pom = minsList.get(i);
		        minsList.set(i, minsList.get(i+1));
		        minsList.set(i+1,pom);
		      }
		    }
		return minsList.get(minsList.size()-1);
	}
	
	public static Col getBi(Matrix A, Matrix x, Integer i) {
		//pro nalezen� minim v jednom ��dku p�i v�po�tu bi
		Matrix A1 = new Matrix (A);
		Matrix x1 = new Matrix(x);
		
		List<Col> listOfMinims = new ArrayList<Col>(); 
		for (int j = 0; j < A1.getColsCount(); j++) {
//			System.out.println("hledam minum pro sloupec " + j + " na radku " + i);
//			System.out.println("A: " + A1.getCol(i,j).getValue() + " x: " + x1.getCol(j,0).getValue());
			listOfMinims.add(min(A1.getCol(i,j),x1.getCol(j,0)));
		}	
//		System.out.println("minima jsou: ");
//		for (int j = 0; j < A1.getColsCount(); j++) {
//			System.out.print(listOfMinims.get(j).getValue() + ",");
//		}
//		System.out.println("maximum je" + maximum(listOfMinims).getValue());
		return maximum(listOfMinims);
	}
	
	public static Matrix multi(Matrix A, Matrix x) {
		//return matrix which is result of multiplication of A and x
		//min(ai1,x1) max min(ai2,x2) max min (ai3,x3) = bi
		Matrix result = new Matrix (A.getRowsCount(), 1);
		for (int i = 0; i < A.getRowsCount(); i++) {
			result.getRows().get(i).getCols().set(0, getBi(A,x,i));
		}
		return result;
	}
	
	public static Matrix multiRowWithMatrix(Row A, Matrix x) {
		//pro vr�cen� matice b, kter� je n�sobkem matice A a x
		//min(ai1,x1) max min(ai2,x2) max min (ai3,x3) = bi
		Matrix result = new Matrix (x.getRowsCount(), 1);
		for (int i = 0; i < x.getRowsCount(); i++) {
			result.setCol(i,0,min(A.getCols().get(i),x.getCol(i, 0)).getValue());
		}
		return result;
	}
	
	public static Row multiRowWithMatrixReturnRow(Row A, Matrix x) {
		//pro vr�cen� ��dku i, kter� je n�sobkem ��dku A a matice x
		//min(ai1,x1) max min(ai2,x2) max min (ai3,x3) ...
		Row result = new Row (A.getColsCount());
		for (int i = 0; i < x.getRowsCount(); i++) {
			result.getCols().get(i).setValue(min(A.getCols().get(i),x.getCol(i, 0)).getValue());
		}
		return result;
	}
	
	public static Boolean isSame (Matrix x1, Matrix x2) {
		Matrix x = new Matrix(x1);
		Matrix y = new Matrix(x2);

		Boolean same = true;
		
		for (int i = 0; i < x.getRowsCount(); i++) {
			for (int j = 0; j < x.getColsCount(); j++) {
				if (!x1.getCol(i, j).getValue().equals(y.getCol(i, j).getValue())) {
					same = false;
					//pokud se alespo� v jednom ��dku nerovnaj�, nerovnaj� se
				}
			}
		}
		return same;
	}
	
//	public static Col getMinFromCols(Row rowA, Matrix x, Integer colIndex) {
//		//pro nalezen� minim v jednom ��dku p�i v�po�tu bi
//		Row r = new Row(rowA);
//		Matrix x1 = new Matrix(x);
//		
//		List<Col> listOfMinims = new ArrayList<Col>(); 
//		for (int j = 0; j < r.getColsCount(); j++) {
////			System.out.println("hledam minum pro sloupec " + j + " na radku " + i);
////			System.out.println("A: " + A1.getCol(i,j).getValue() + " x: " + x1.getCol(j,0).getValue());
//			listOfMinims.add(min(r.getCols().get(j),x1.getCol(j,0)));
//		}	
////		System.out.println("minima jsou: ");
////		for (int j = 0; j < A1.getColsCount(); j++) {
////			System.out.print(listOfMinims.get(j).getValue() + ",");
////		}
////		System.out.println("maximum je" + maximum(listOfMinims).getValue());
//		return maximum(listOfMinims);
//	}
}
